#include "string.h"
#include "stdlib.h"
#include "stdarg.h"

#include "xlx_define.h"
#include "xlx_func.h"
#include "xlx_core.h"
#include "xlx_parse_body.h"

#define TUTUBUFMAX 2048
static u16 tcp_pkg_seq = 0;
static char g_tutuapi_recvbuf[TUTUBUFMAX] = {'\0'};
static int g_tutuapi_recv_size = 0;

static TutuMsgHead g_tutuapi_head = {0};

extern int get_version_code(void);
extern int get_device_type_id(void);

static void tutuapi_on_recv_data(void * buf,int len){
    char again = 1;//继续解包
    if(len <= 0){
        return;
    }

    TUTULOG("[ffly] recv server data len=%d",len);

    if(len + g_tutuapi_recv_size >= TUTUBUFMAX){
        TUTULOG("[ffly] recv data length out of range!!!!!!\n");
        g_tutuapi_recv_size = 0;
        return;
    }

    //写入数据到缓存中
    memcpy(g_tutuapi_recvbuf + g_tutuapi_recv_size,buf,len);
    g_tutuapi_recv_size += len;
    
    while(again == 1){
        again = 0;//重置解包状态

        //检测头长度
        if(g_tutuapi_recv_size >= 8){
            
            char *data = g_tutuapi_recvbuf;
            
            //读取包头数据
            memcpy(&g_tutuapi_head, data, 8);
            
            //比对固定前缀
            //明文还是加密
            if(g_tutuapi_head.fixed == FIXED_OPEN || g_tutuapi_head.fixed == FIXED_SAFE){
                int pkglen = 0;
                if(tutu_is_bigendian == 0){
                    g_tutuapi_head.body_len = xlx_htons(g_tutuapi_head.body_len);
                    g_tutuapi_head.crc16 = xlx_htons(g_tutuapi_head.crc16);
                    g_tutuapi_head.seq = xlx_htons(g_tutuapi_head.seq);
                }
                
                pkglen = 8 + g_tutuapi_head.body_len;
                //数据长度 = 头+包体
                if(g_tutuapi_recv_size >= pkglen){
                    tutubody_callfunc(&g_tutuapi_head, g_tutuapi_recvbuf+8, g_tutuapi_head.body_len);

                    g_tutuapi_recv_size -= pkglen;
                    if(g_tutuapi_recv_size > 0){
                        memcpy(g_tutuapi_recvbuf,g_tutuapi_recvbuf+pkglen,g_tutuapi_recv_size);
                        again = 1;//如果还有包没解析完，继续解析下一个包
                    }
                }
            }
            
        }//检测头长度
    }
}

//事件：连接被关闭
static void tutuapi_on_disconnect(void){
    g_tutuparam.server_connected = 3;
    g_tutuparam.is_login_server = 0;
    TUTULOG("disconnect server!!");
}

static void tutuapi_on_connect_success(void){
    TUTULOG("connect server success!!");
    char iccid[32]={0};
    
    TutuMsgLogin login = {0};
    memcpy(login.imei, g_tutuconfig.imei, 8);
    login.deviceid = get_device_type_id();
    login.soft_vercode = get_version_code();
    
    strcpy(iccid, TEST_ICCID);
    //char转bcd编码
    xlx_char2bcd(iccid,20,login.iccid);
    g_tutuparam.server_connected = 1;
    tutuapi_send_login_msg(&login);
}

//过滤包是否要存到离线，下次上线后继续可以发送
//返回 1：保存到离线区，0：不保存
static char tutuapi_on_filter_pkg_tobackup(char *buf,int len){
    if(len > 2){
        char c = 0;
        c = *(buf+1);
        if(c == CMD_UPLOAD_GPS || c == CMD_UPLOAD_GPS_MORE){
            //如果是单gps包、多gps包，则保存离线，下次登录，继续传递给服务器
            return 1;
        }
    }
    return 0;
}

void tutuapi_init(void){
    TUTULOG("sys_init: %s(%d)", __FUNCTION__, __LINE__);
}

//连接到服务器
int tutuapi_connect_server(){
    TutuTcpCb cb = {0};
    cb.on_connect_success = tutuapi_on_connect_success;
    cb.on_recv_data = tutuapi_on_recv_data;
    cb.on_disconnect = tutuapi_on_disconnect;
    cb.on_filter_pkg_tobackup = tutuapi_on_filter_pkg_tobackup;
    
    g_tutuparam.server_connected = 2;

    g_tututcp.allow_writing(0);

    //如果之前联网过，需要先检测把之前的资源释放掉
    g_tututcp.close_server();

    //域名自动解析成ip
    g_tututcp.connect_server(g_tutuservercfg.server_host, g_tutuservercfg.server_port,&cb);

    TUTULOG("try connect server %s:%d",g_tutuservercfg.server_host, g_tutuservercfg.server_port);
    return 0;
}

/**
 * 填充封包格式头内容,需要在最前面预留sizeof(TutuMsgHead)大小
 * @param cmd 命令号
 * @param seq 包序列号
 * @param sndbuf 待发送内容大小=head + body
 * @param len 包体长度
 */
void tutuapi_fill_head(u8 cmd,u16 seq,char *sndbuf,int bodylen){
    int headlen = sizeof(TutuMsgHead);

    TutuMsgHead head = {0};
    head.fixed = FIXED_OPEN;
    head.cmd = cmd;
    head.body_len = bodylen;
    head.seq = seq;
    head.crc16 = 0;
    
    if(tutu_is_bigendian == 0){
        head.seq = xlx_htons(head.seq);
        head.body_len = xlx_htons(head.body_len);
    }
    
    //把协议头数据写入到缓存
    memcpy(sndbuf, &head, headlen);
    
    //crc后面的内容都需要参与计算
    head.crc16 =xlx_crc16(sndbuf + 4, bodylen + 4);

    if(tutu_is_bigendian == 0){
        head.crc16 = xlx_htons(head.crc16);
    }
    
    sndbuf[2] = head.crc16 & 0xff;
    sndbuf[3] = head.crc16 >> 8;
}

/*
 * 追加协议头 
 * @param cmd 命令号
 * @param sndbuf 待发送内容，内容需要预留前面的head部分
 * @param bodylen 包体长度
 */
void tutuapi_append_head(u8 cmd,char *sndbuf,int bodylen){
    u16 seq = tcp_pkg_seq++;
    tcp_pkg_seq = tcp_pkg_seq % 0xffff;
    tutuapi_fill_head(cmd,seq,sndbuf,bodylen);
}

/**
 * 发送数据包到服务器
 * @param sndbuf 发送缓冲区
 * @param bufsize 发送缓冲区大小
 * @param cmd 命令号
 * @param bodydata 待发送包体内容
 * @param bodylen 包体长度
 * 
 * @return 1:发送   0：失败
 */
int tutuapi_send_buffer(char *sndbuf,int bufsize,u8 cmd,char *bodydata,int bodylen){
    int headlen = sizeof(TutuMsgHead);

    //检测长度是否越界,缓冲区大小是否装的下内容
    if(headlen + bodylen > bufsize){
        TUTULOG("------------send buff failt!!!!!!!!---headlen + bodylen > bufsize-----------------");
        return 0;
    }

    if(bodylen > 0){
        //填充包体内容
        memcpy(sndbuf + headlen,bodydata,bodylen);
    }

    //填充包头
    tutuapi_append_head(cmd,sndbuf,bodylen);

    return g_tututcp.write(sndbuf,headlen + bodylen);
}

/**
 * 强制发送数据包到服务器
 * @param sndbuf 发送缓冲区
 * @param bufsize 发送缓冲区大小
 * @param cmd 命令号
 * @param bodydata 待发送包体内容
 * @param bodylen 包体长度
 * 
 * @return 1:发送   0：失败
 */
int tutuapi_force_send_buffer(char *sndbuf,int bufsize,u8 cmd,char *bodydata,int bodylen){
    int headlen = sizeof(TutuMsgHead);

    //检测长度是否越界,缓冲区大小是否装的下内容
    if(headlen + bodylen > bufsize){
        TUTULOG("------------send buff failt!!!!!!!!---headlen + bodylen > bufsize-----------------");
        return 0;
    }

    if(bodylen > 0){
        //填充包体内容
        memcpy(sndbuf + headlen,bodydata,bodylen);
    }

    //填充包头
    tutuapi_append_head(cmd,sndbuf,bodylen);

    return g_tututcp.force_write(sndbuf,headlen + bodylen);
}

//发起登录认证
void tutuapi_send_login_msg(TutuMsgLogin *login){
    char buf[64]={0};
    int ret = 0;
    if(tutu_is_bigendian==0){
        login->deviceid = xlx_htons(login->deviceid);
        login->soft_vercode = xlx_htonl(login->soft_vercode);
    }

    ret = tutuapi_force_send_buffer(buf,64,CMD_LOGIN,(char*)login,sizeof(TutuMsgLogin));
    TUTULOG("\nsend login: status=%d\n",ret);
}

/*
* 发送心跳数据
* 增加休眠状态/本次休眠时间
*/
void tutuapi_send_heart_msg(TutuMsgHeart *heart){
    int ret = 0;
    int len = sizeof(TutuMsgHeart);
    char buf[64]={0};
    char tmp[64]={0};

    memcpy(tmp,heart,len);
    TUTUSprintf(tmp+len,"v=%d,usb=%d,chrg=%d", 3992, 0, 0);   

    ret = tutuapi_send_buffer(buf,64,CMD_HEART,tmp, len + strlen(tmp+len));
    TUTULOG("\nsend heart: status=%d\n",ret);
}

void tutuapi_send_heart_msg2(){
    TutuMsgHeart heart = {0};
    heart.power = g_tutuparam.device_status.power;
    heart.gsm = g_tutuparam.device_status.gsm_signal;
    heart.satellites = g_tutuparam.device_status.satellite_size;
    heart.device_state = g_tutuparam.device_status.status;
    tutuapi_send_heart_msg(&heart);
}

//请求同步服务器时间
void tutuapi_send_synctime_msg(void){
    int ret = 0;
    char buf[32]={0};
    ret = tutuapi_send_buffer(buf,32,CMD_SYNCTIME,0, 0);

    TUTULOG("\nsend synctime: status=%d\n",ret);
}

/**
 * 上传声控报警
 * @param buffer 发送缓冲区
 * @param total 文件总共切片数量
 * @param seq 当前序号
 * @param data 音频数据
 * @param len 音频数据长度
 */
void tutuapi_send_upload_audio_msg(TutuSndBuffer *buffer,int total,int seq,const char *data,int len){
    int ret = 0;
    int headlen = sizeof(TutuMsgHead);
    int bodylen = len + 2;

    //检测缓存区是否足够
    if(bodylen + headlen < buffer->bufsize){
        buffer->buf[headlen] = total;
        buffer->buf[headlen+1] = seq;
        //填充body
        memcpy(buffer->buf+headlen+2,data,len);

        //填充head
        tutuapi_append_head(CMD_UPLOAD_AUDIO,buffer->buf,bodylen);
        ret = g_tututcp.write_audio(buffer->buf,headlen + bodylen);//发送声控报警，使用另外一个优先级
    }else{
        TUTULOG("Send audio buff failt!!!!!!!!--->headlen+bodylen: %d > bufsize: %d", bodylen + headlen, buffer->bufsize);
    }

    TUTULOG("send audio: status=%d  total=%d seq=%d len=%d",ret,total,seq,bodylen);
}

void tutuapi_send_upload_audio2_msg(TutuSndBuffer *buffer,int total,int seq,const char *data,int len, int format){
    int ret = 0;
    int headlen = sizeof(TutuMsgHead);
    int bodylen = len + 3;

    //检测缓存区是否足够
    if(bodylen + headlen < buffer->bufsize){
        buffer->buf[headlen] = total;
        buffer->buf[headlen+1] = seq;
        buffer->buf[headlen+2] = format;       //音频格式，0：AMR，1：WAV
        //填充body
        memcpy(buffer->buf+headlen+3,data,len);

        //填充head
        tutuapi_append_head(CMD_UPLOAD_FORMAT_AUDIO,buffer->buf,bodylen);
        ret = g_tututcp.write_audio(buffer->buf,headlen + bodylen);//发送声控报警，使用另外一个优先级
    }else{
        TUTULOG("Send audio buff failt!!!!!!!!--->headlen+bodylen: %d > bufsize: %d", bodylen + headlen, buffer->bufsize);
    }

    TUTULOG("send audio: status=%d  total=%d seq=%d len=%d",ret,total,seq,bodylen);
}

int tutuapi_get_audio_msg_count() {
    return g_tututcp.audio_msg_count();
}

int tutuapi_get_audio_queue_count() {
    return g_tututcp.audio_queue_count();
}

char __pri_net_logger_buf[1024]={0};
/*打印网络日志*/
void tutuapi_send_net_logger_print(const char* fmt, ...){
    int headlen = sizeof(TutuMsgHead);
    int bodylen = 0;
    int len = 0;

    va_list args;
    va_start(args,fmt);
    TUTUVsnprintf(__pri_net_logger_buf,sizeof(__pri_net_logger_buf),fmt,args);
    va_end(args);

    bodylen = strlen(__pri_net_logger_buf);
    len = bodylen + headlen;

    if(tutu_net_logger == 1 && g_tutuparam.is_login_server == 1 && g_tututcp.is_connect() == 1){
        char *buffer = (char*)TUTUAlloc(len);
        char *body = (buffer + headlen);
        
        //填充body数据
        memset(buffer, 0, len);
        memcpy(body,__pri_net_logger_buf,bodylen);

        //填充head
        tutuapi_append_head(CMD_NET_LOGGER,buffer,bodylen);

        //发送数据到服务器
        g_tututcp.write(buffer,headlen + bodylen);

        TUTUFree(buffer);
    }
}

/**
 * 发送网络日志到服务器
 * @param buffer 发送缓冲
 * @param logger 日志字符串
 */
void tutuapi_send_net_logger(TutuSndBuffer *buffer,const char *logger){
    int ret = 0;
    int headlen = sizeof(TutuMsgHead);
    int bodylen = strlen(logger);

    if(bodylen + headlen < buffer->bufsize){
        //填充body
        memcpy(buffer->buf + headlen,logger,bodylen);

        //填充head
        tutuapi_append_head(CMD_NET_LOGGER,buffer->buf,bodylen);
        ret = g_tututcp.write(buffer->buf,headlen + bodylen);
    }else{
        TUTULOG("------------send net logger buff failt!!!!!!!!---headlen + bodylen > bufsize-----------------");
    }
    TUTULOG("\nsend net logger: status=%d\n",ret);
}

/**
 * 上传告警
 * @param alert 告警基本数据
 * @param data 多个告警事件内容
 * @param len 数据长度
 */
void tutuapi_send_upload_alert_msg(TutuMsgAlert *alert,const char*data,int len){
    char sndbuf[1024];
    int ret = 0;
    int alert_len = sizeof(TutuMsgAlert);
    int headlen = sizeof(TutuMsgHead);
    int bodylen = len + alert_len;
    
    if(tutu_is_bigendian == 0){
        alert->upload_time = xlx_htonl(alert->upload_time);
    }

    if(bodylen + headlen < 1024){
        //填充body
        memcpy(sndbuf + headlen, alert, alert_len);
        memcpy(sndbuf + headlen + alert_len,data,len);

        //填充head
        tutuapi_append_head(CMD_UPLOAD_ALERT,sndbuf,bodylen);
        ret = g_tututcp.write(sndbuf,headlen + bodylen);
    }else{
        TUTULOG("------------send alert buff failt!!!!!!!!---headlen + bodylen > bufsize-----------------");
    }
    TUTULOG("\nsend alert: status=%d\n",ret);
}

//填充wifi数据
int tutuapi_load_wifi(char *buf,TutuMsgWifi **wifi_list,int wifi_size){
    int i = 0;
    char *p = buf;
    TutuMsgWifi *wifi = 0;
    for(i = 0;i < wifi_size;i++){
        wifi = wifi_list[i];
        if(wifi){
            memcpy(p, wifi->mac, 6);p += 6;
            (*p) = wifi->ssid_len;p++;
            memcpy(p, wifi->ssid, wifi->ssid_len);p += wifi->ssid_len;
            (*p) = wifi->signal;p++;
        }
    }
    return (int)(p - buf);
}

//填充基站数据
int tutuapi_load_station(char *buf,TutuMsgBaseStation **station_list,int station_size){
    int i = 0;
    char *p = buf;
    TutuMsgBaseStation station = {0};    
    for(i = 0;i < station_size;i++){
        if(station_list[i]){     //lzj fixed, 修复数据，这里不能直接用指针，否则会改变原始数据
            memcpy(&station, station_list[i], sizeof(TutuMsgBaseStation));
            if(tutu_is_bigendian == 0){
                station.mcc = xlx_htons(station.mcc);
                station.mnc = xlx_htons(station.mnc);
                station.lac = xlx_htons(station.lac);
                station.cellid = xlx_htonl(station.cellid);
            }
            memcpy(p, &station, sizeof(TutuMsgBaseStation));
            p += sizeof(TutuMsgBaseStation);
        }
    }
    return (int)(p - buf);
}

//填充蓝牙数据
int tutuapi_load_bluetooth(char *buf,TutuMsgBluetooth **blue_list,int blue_size){
    int i = 0;
    char *p = buf;
    TutuMsgBluetooth *blue = 0;
    for(i = 0;i < blue_size;i++){
        blue = blue_list[i];
        if(blue){
            memcpy(p, blue->mac, 6);p += 6;
            (*p) = blue->bluetooth_len;p++;
            memcpy(p, blue->bluetooth, blue->bluetooth_len);p += blue->bluetooth_len;
            (*p) = blue->signal;p++;
        }
    }
    return (int)(p - buf);
}

#if 0
//填充gps数据
int tutuapi_load_gps(char *buf,TutuMsgGps *gps){
    int size = sizeof(TutuMsgGpsBodyHead);
    char *p = buf;
    TutuMsgGpsBodyHead head = {0};

    if(gps){
        memcpy(&head,&(gps->head),size);
        head.upload_time = xlx_htonl(gps->head.upload_time);
        head.lat = xlx_htonll(gps->head.lat);
        head.lng = xlx_htonll(gps->head.lng);
        head.altitude = xlx_htons(gps->head.altitude);
        head.state = xlx_htons(gps->head.state);

        head.base_station_size = head.base_station_size > 6 ? 6: head.base_station_size;
        head.wifi_size = head.wifi_size > 6 ? 6 : head.wifi_size;
        head.bluetooth_size = head.bluetooth_size > 6 ? 6 :head.bluetooth_size;
        
        memcpy(p,&head,size);
        p += size;

        p += tutuapi_load_station(p, gps->station_list, head.base_station_size);
        
        p += tutuapi_load_wifi(p,gps->wifi_list,head.wifi_size);
        
        p += tutuapi_load_bluetooth(p, gps->blue_list, head.bluetooth_size);
    }
    
    
    return (int)(p - buf);
}

//上报单个gps位置
void tutuapi_send_uploadgps_msg(TutuMsgGps *gps){
    int ret = 0;
    int headlen = sizeof(TutuMsgHead);
    int bodylen = 0;
    if(gps){
        char sndbuf[1024] = {'\0'};
        char *p = sndbuf;

        p += headlen;//预留head区域
        p += tutuapi_load_gps(p,gps);
        bodylen = (int)(p - sndbuf) - headlen;

        if(headlen + bodylen < 1024){
            //填充head
            tutuapi_append_head(CMD_UPLOAD_GPS,sndbuf,bodylen);
            ret = g_tututcp.write(sndbuf,headlen + bodylen);
        }else{
            TUTULOG("------------send single gps buff failt!!!!!!!!---headlen + bodylen > bufsize-----------------");
        }

        TUTULOG("\nsend single gps: status=%d\n",ret);
    }
}

/**
 * 拷贝nmea格式数据到gps结构中
 */
void tutuapi_nmea_copyto_gps(TutuNmeaMsg* recv,TutuMsgGps *snd){
    if(recv && snd){
        uint32_t timestamp = 0;
        uint32_t timestamp2 = 0;
        TutuTime t = {0};
        t.year = recv->utc.year;
        t.mon = recv->utc.month;
        t.day = recv->utc.date;
        t.hour = recv->utc.hour;
        t.min = recv->utc.min;
        t.sec = recv->utc.sec;

        timestamp = tutu_2timestamp_fast(&t);
        timestamp2 = g_tutuos.get_utc_timestamp();
        if(timestamp > timestamp2 + 7500){//gps时间修正
            timestamp = timestamp2;
        }

        snd->head.upload_time = timestamp;//g_tutuos.get_utc_timestamp();
        snd->head.satellites = recv->posslnum;
        snd->head.lat = recv->latitude;
        snd->head.lng = recv->longitude;
        snd->head.speed = recv->speed;
        snd->head.altitude = (u16)(recv->altitude/10);//单位m,海拔有可能是负数，需要自行处理
        
        
        if(recv->nshemi == 's' || recv->nshemi == 'S'){
            //北纬/南纬,N:北纬;S:南纬
            snd->head.state |= (1<<14);
        }

        if(recv->ewhemi == 'e' || recv->ewhemi == 'E'){
            //东经/西经,E:东经;W:西经
            snd->head.state |= (1<<15);
        }

        if(recv->gpssta > 0){
            //GPS已定位
            snd->head.state |= (1<<13);
        }

        //航向，占10bit
        snd->head.state |= (0x3ff & (recv->direct/100));
    }
}

void tutuapi_send_uploadgps_msg2(){
    TutuMsgGps snd = {0};
    TutuNmeaMsg *recv = 0;

    recv = g_tutugps.get_gps_info();

    if(recv && recv->gpssta > 0){
        tutuapi_nmea_copyto_gps(recv,&snd);
        tutuapi_send_uploadgps_msg(&snd);
    }
}

//上报多个gps位置
void tutuapi_send_gpsmore_msg(TutuSndBuffer *buffer,TutuMsgGps **gps_list,int gps_size){
    char *p = buffer->buf;
    int i = 0;
    TutuMsgGps *gps = 0;
    int ret = 0;
    int headlen = sizeof(TutuMsgHead);
    int bodylen = 0;

    if(gps_size > 0){
        p += headlen;//预留head空间
        
        *p = gps_size;
        p++;

        for (i = 0; i < gps_size; i++) {
            gps = gps_list[i];
            if(gps){
                p += tutuapi_load_gps(p,gps);
            }
        }

        bodylen = (int)(p - buffer->buf) - headlen;

        if(bodylen + headlen > buffer->bufsize){
            TUTULOG("------------send gps list buff failt!!!!!!!!---headlen + bodylen > bufsize-----------------");
            return;
        }

        //填充head
        tutuapi_append_head(CMD_UPLOAD_GPS_MORE,buffer->buf,bodylen);
        ret = g_tututcp.write(buffer->buf,headlen + bodylen);

        TUTULOG("\nsend mul gps: status=%d\n",ret);
    }
}
#endif


/*上报设备状态*/
void tutuapi_send_device_status_msg(void){
    int ret = 0;
    int headlen = sizeof(TutuMsgHead);
    int bodylen = 0;
    char sndbuf[256] = {'\0'};
    char *body = sndbuf + headlen;

    int workPattern = 0;//定位时间（秒）
    int record = 0;//声控报警开关： 0：关闭，1：智能声控报警，2：持续声控报警
    int shake = 0;//震动提醒： 0:关闭，1：开启
    int persistRecord = 0;//持续声控报警设置：时间(秒)
    int airplaneMode = 0;//飞行模式设置：时间(分)
    int recordDuration = 0;//声控报警时长设置:  时间（秒）
    int inflectionPoint = 0;//拐点补传： 0:关闭，1：开启
    int dismantle = 0;//拆除报警：0:关闭，1：开启
    int onOff = 0;//远程开关机： 0:关闭，1：开启


    //gps间隔时间
    workPattern = g_tutuconfig.gps_inteval;

    //声控报警模式
    if(g_tutuconfig.audio_mode.mode == 3){
        record = 1;//智能声控报警
    }else if(g_tutuconfig.audio_mode.mode == 2){
        record = 2;//持续声控报警
    }
    persistRecord = g_tutuconfig.audio_mode.hold_time_final;
    recordDuration = g_tutuconfig.audio_mode.file_longtime;
    
    //开启拐弯补传
    if((g_tutuconfig.enable_status & ENABLE_TURN)!=0){
        inflectionPoint = 1;
    }

    //开启拆卸
    if((g_tutuconfig.enable_status & ENABLE_UNINSTALL) != 0){
        dismantle = 1;
    }

    //开启震动
    if((g_tutuconfig.enable_status & ENABLE_SHAKE) != 0){
        shake = g_tutuconfig.shake_alert_enable;
    }


    //飞行模式
    if(g_tutuconfig.fly_mode.enable == 1){
        airplaneMode = g_tutuconfig.fly_mode.exit_time;
    }

    TUTUSprintf(body,"workPattern=%d,record=%d,shake=%d,persistRecord=%d,airplaneMode=%d,recordDuration=%d,inflectionPoint=%d,dismantle=%d,onOff=%d,mode=%d",
    workPattern,record,shake,persistRecord,airplaneMode,recordDuration,inflectionPoint,dismantle,onOff,g_tutuconfig.mode);
    bodylen = strlen(body);

    if(bodylen + headlen > 256){
        TUTULOG("------------send device status buff failt!!!!!!!!---headlen + bodylen > bufsize-----------------");
        return;
    }

    //填充head
    tutuapi_append_head(CMD_DEVICE_STATUS,sndbuf,bodylen);
    ret = g_tututcp.write(sndbuf,headlen + bodylen);

    TUTULOG("\nsend device status: status=%d\n",ret);
}

/**
 * 上报复合定位信息
 * @param buffer 发送缓冲
 * @param station_list 多个基站数据
 * @param station_size 基站个数
 * @param wifi_list 多个wifi数据
 * @param wifi_size wifi个数
 * @param blue_list 多个蓝牙数据
 * @param blue_size 蓝牙个数
 */
void tutuapi_send_lbs_msg(
    TutuSndBuffer *buffer,
    TutuMsgBaseStation **station_list,int station_size,
    TutuMsgWifi **wifi_list,int wifi_size,
    TutuMsgBluetooth **blue_list,int blue_size
                          ){
    uint32_t uptime = 0;
    int ret = 0;
    int bodylen = 0;
    int headlen = sizeof(TutuMsgHead);
    char *p = buffer->buf;

    station_size = station_size > 6 ? 6 : station_size;
    wifi_size = wifi_size > 6 ? 6 : wifi_size;
    blue_size = blue_size > 6 ? 6 : blue_size;
    
    p += headlen;//给head留出空间
    (*p) = station_size;p++;
    (*p) = wifi_size;p++;
    (*p) = blue_size;p++;

    //下面填充body的数据要避免超过2048，造成内存溢出
    
    p += tutuapi_load_station(p, station_list, station_size);
    
    p += tutuapi_load_wifi(p,wifi_list,wifi_size);
    
    p += tutuapi_load_bluetooth(p, blue_list, blue_size);
    
    //1:需要服务器回复经纬度，0：不需要回复经纬度
    (*p) = 0;p++;
    
    //lbs采集时间
    uptime = xlx_htonl(g_tutuos.get_utc_timestamp());
    memcpy(p,&uptime,4);p += 4;

    bodylen = (int)(p - buffer->buf) - headlen;

    if(bodylen + headlen > buffer->bufsize){
        TUTULOG("------------send lbs buff failt!!!!!!!!---headlen + bodylen > bufsize-----------------");
        return;
    }
    
    //填充head
    tutuapi_append_head(CMD_UPLOAD_LBS,buffer->buf,bodylen);
    ret = g_tututcp.write(buffer->buf,headlen + bodylen);
    
    TUTULOG("\nsend lbs: status=%d\n",ret);
}


/**
 * 回复指令响应
 * @param actionid 任务id
 * @param data 指令内容
 * @param len 指令内容长度
 */
void tutuapi_send_stringaction(u16 actionid,const char *data,int len){
    int ret = 0;
    u16 var16 = 0;
    int headlen = sizeof(TutuMsgHead);
    int bodylen = len + 2;
    char sndbuf[1024] = {'\0'};
    var16 = xlx_htons(actionid);

    //检测缓存区是否足够
    if(bodylen + headlen < 1024){
        sndbuf[headlen] = var16 >> 8;
        sndbuf[headlen+1] = var16 & 0xff;

        //填充body
        memcpy(sndbuf+headlen+2,data,len);

        //填充head
        tutuapi_fill_head(CMD_STRING_COMMAND,actionid,sndbuf,bodylen);
        ret = g_tututcp.write(sndbuf,headlen + bodylen);
    }else{
        TUTULOG("------------send stringaction buff failt!!!!!!!!---headlen + bodylen > bufsize-----------------");
    }
    

    TUTULOG("\nsend string command: seq=%x status=%d\n",actionid,ret);
}

//上报单个气压和温度值
void tutuapi_send_upload_air_msg(TutuMsgAir *airInfo){
    int ret = 0;
    int headlen = sizeof(TutuMsgHead);
    int bodylen = 0;
    if(airInfo){
        char sndbuf[1024] = {'\0'};
        char *p = sndbuf;

        p += headlen;//预留head区域
        *p = 0;  p++;    //channel
        *p = 0;  p++;     //version
        u32 press = xlx_htonl(airInfo->press);
        memcpy(p, &press, 4); p += 4;       //气压
        u32 temp = xlx_htonl(airInfo->temp);          
        memcpy(p, &temp, 4); p += 4;        //温度
        *p = airInfo->satellites; p++;      //卫星数
        u16 altitude = xlx_htons(airInfo->altitude);   
        memcpy(p, &altitude, 2); p += 2;    //海拔
        *p = airInfo->floor;    p++;        //楼层，0xff无效

        if (airInfo->station_size == 0) {       //没有基站信息的时候，要数据占位
            p += sizeof(TutuMsgBaseStation);     
        } else {
            p += tutuapi_load_station(p, airInfo->station_list, airInfo->station_size);
        }

        *p = airInfo->wifi_size > 6 ? 6 : airInfo->wifi_size;   p++;
        p += tutuapi_load_wifi(p, airInfo->wifi_list, airInfo->wifi_size > 6 ? 6 : airInfo->wifi_size);

        bodylen = (int)(p - sndbuf) - headlen;
        if(headlen + bodylen < 1024){
            //填充head
            tutuapi_append_head(CMD_TRANS_DATA,sndbuf,bodylen);
            ret = g_tututcp.write(sndbuf,headlen + bodylen);
        }else{
            TUTULOG("------------send single air buff failt!!!!!!!!---headlen + bodylen > bufsize-----------------");
        }

        TUTULOG("\nsend single air status=%d lbsSize:%d wifiSize:%d\n", ret, airInfo->station_size, airInfo->wifi_size);
    }
}